/* Copyright 2001,2002,2003 NAH6
 * All Rights Reserved
 *
 * Parts Copyright DoD, Parts Copyright Starium
 *
 */
#include "calc_adapt_conv.h"
#include "main.h"
#include <assert.h>

/**************************************************************************
*
* ROUTINE
*               CalcAdaptConv
*
* FUNCTION
*               Calculate and save convolution of truncated impulse
*               response.
* SYNOPSIS
*               CalcAdaptConv(pc_imp, len_trunc, Exc, Exc_len, conv);
*
*   formal
*
*                       data    I/O
*       name            type    type    function
*       -------------------------------------------------------------------
*       pc_imp          fxpt_16  i      Impulse response of PCs
*       len_trunc       int      i      Length to truncate impulse response
*       Exc             fxpt_16  i      Excitation vector
*       Exc_len         int      i      Lenght of excitation vector
*       conv            fxpt_16  o      Truncated convolved impulse response
*
**************************************************************************
           Calculate and save convolution of truncated (to len)
           impulse response for first lag of t (=mmin) samples:

                min(i, len)
           y     =  SUM  h * ex       , where i = 1, ..., L points
            i, t    j=1   j    i-j+1

                      h |1 2...len x x|
           ex |L . . . 2 1|             = y(1)
             ex |L . . . 2 1|           = y(2)
                           :              :
                     ex |L  . . .  2 1| = y(L)
**************************************************************************/


/*  Prior implementation
 *
 *   void CalcAdaptConv(
 *   fxpt_16    pc_imp[],                       // 2.13 format
 *   int        len_trunc,
 *   fxpt_16    Exc[],                          // 15.0 format
 *   int        Exc_len,
 *   fxpt_16    conv[])                         // 15.0 format
 *   {
 *     int      i, j;
 *     int      limit;
 *     int64 acc;
 *
 *     FXPT_PUSHSTATE("CalcAdaptConv", -1.0, -1.0);
 *
 *     // Calculate convolution
 *     for (i = 0; i < Exc_len; i++) {
 *
 *       acc = 0;
 *       limit = min (i, len_trunc);
 *       for(j = 0; j <= limit; j++) {
 *         // conv[i] += pc_imp[j] * Exc[i-j];
 *         acc += pc_imp[j] * Exc[i-j];
 *       }
 *       conv[i] = acc >> 13;
 *     }
 *
 *     FXPT_POPSTATE();
 *   }
 */


/*
 *  Now implemented as 1 loop again, after optimization by bigmac.
 */

#if 1

void CalcAdaptConv(
fxpt_16 pc_imp[],                       /* 2.13 format */
fxpt_16 Exc[],                          /* 15.0 format */
fxpt_32 conv[])                         /* 18.13 format */
{
  int   i, j;
  fxpt_32 acc;
  fxpt_16 *pp,*pe;
  fxpt_32 *pc;

  /* Calculate convolution */
  for (i= 0, pc= conv ; i < SF_LEN; ++i,++pc) {
    acc = 0;
    for(j= min(i,LEN_TRUNC_H), pp= pc_imp, pe= Exc+i; j>0; --j,++pp,--pe) {
      acc= fxpt_add32( acc, *pp * *pe );
    }
    *pc = acc;
  }
}

#else


void CalcAdaptConv(
fxpt_16 pc_imp[],                       /* 2.13 format */
fxpt_16 Exc[],                          /* 15.0 format */
fxpt_32 conv[])                         /* 18.13 format */
{
  int   i, j;
  int64 acc;

  /* Calculate convolution */

  for (i = 0; i < LEN_TRUNC_H; i++) {
    acc = 0;
    for(j = 0; j <= i; j++) {
      acc += pc_imp[j] * Exc[i-j];
    }
    conv[i] = fxpt_saturate32(acc);
  }

  /*
   *  To be 100% compatible with the previous implementation the inner loop would
   *  have to be written <= 30.  I'm making it "<", since 30 can be unrolled and
   *  31 cannot.  (LEN_TRUNC_H is 30).
   */

  for (i = LEN_TRUNC_H; i < SF_LEN; i++) {
    acc = 0;
    for (j = 0; j <= LEN_TRUNC_H; j++) {		// = put back in by bigmac
      acc += pc_imp[j] * Exc[i-j];
    }
//    conv[i] = fxpt_saturate16(acc >> 13);
    conv[i] = fxpt_saturate32(acc);
  }

}

#endif

